package com.premadefood.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.premadefood.common.ErrorCode;
import com.premadefood.domain.*;
import com.premadefood.domain.vo.GoodsVO;
import com.premadefood.exception.BusinessException;
import com.premadefood.mapper.UserMapper;
import com.premadefood.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.premadefood.constant.UserConstant.USER_LOGIN_STATE;

/**
* @author 23854
* @description 针对表【user】的数据库操作Service实现
* @createDate 2024-02-27 16:10:49
*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService {

    //盐值混淆密码
    private  static final String SALT = "GuQin";

    private final Gson gson = new Gson();
    @Resource
    private UserMapper userMapper;

    @Resource
    private GoodsService goodsService;

    @Resource
    private GoodsviewhistoryService goodsviewhistoryService;

    @Resource
    private StorefocusService storefocusService;

    @Resource
    private MsgCenterService msgCenterService;

    @Resource
    private MsgService msgService;

    @Resource
    private UserorderService userorderService;


    @Override
    public User userRegister(String userAccount, String userPassword, String checkPassword,
                             HttpServletRequest request) {
        //1.校验
        if(StringUtils.isAnyBlank(userAccount,userPassword,checkPassword)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"参数为空");
        }

        //账户不能包含特殊字符
        final String SYMBOL_PATTERN = "[!@#$%^&*()\\-=_+\\[\\]{};':\"\\\\|,.<>/?]";
        Pattern pattern = Pattern.compile(SYMBOL_PATTERN);
        Matcher matcher = pattern.matcher(userAccount);

        if(matcher.find()) {
            throw new BusinessException(ErrorCode.WRONG_ACCOUNT,"账号不能包含特殊字符");
        }


        //密码要与校验密码相同
        if(!userPassword.equals(checkPassword)){
            throw new BusinessException(ErrorCode.PWD_MUST_SAME,"两次密码输入不一致");
        }

        //账户不能重复
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        lqw.eq(User::getAccount,userAccount);
        long count = this.count(lqw);
        if(count > 0){
            throw new BusinessException(ErrorCode.IS_EXISTS,"账户不能重复");
        }

        //对密码进行加密
        //在此处可以进行加盐操作

        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());


        //插入数据
        User user = new User();
        user.setAccount(userAccount);
        user.setPassword(encryptPassword);
        boolean saveResult = this.save(user);

        if(!saveResult)
            return null;

        User safeUser = this.getSafeUser(user);
        request.getSession().setAttribute(USER_LOGIN_STATE,safeUser);

        return user;
    }

    @Override
    public User userLogin(String userAccount, String userPassword, HttpServletRequest request) {
        //1.校验
        if(StringUtils.isAnyBlank(userAccount,userPassword)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"账号或密码不能为空");
        }




        //账户不能包含特殊字符
        String SYMBOL_PATTERN = "[!@#$%^&*()\\-=_+\\[\\]{};':\"\\\\|,.<>/?]";
        Pattern pattern = Pattern.compile(SYMBOL_PATTERN);
        Matcher matcher = pattern.matcher(userAccount);

        if(matcher.find()) {
            log.info("userLogin failed, userAccount cannot match userPassword");
            throw new BusinessException(ErrorCode.WRONG_ACCOUNT,"账号不能包含特殊字符");
        }




        //对密码进行加密
        //在此处可以进行加盐操作
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());

        //查询用户是否存在
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        lqw.eq(User::getAccount,userAccount).eq(User::getPassword,encryptPassword);
        User user = this.getOne(lqw);

        //用户不存在
        if(user == null){
            log.info("userLogin failed, userAccount cannot match userPassword");
            throw new BusinessException(ErrorCode.WRONG_PWD,"账户密码不匹配");
        }



        //用户脱敏

        User safeUser = getSafeUser(user);
        //记录用户的登录态
        request.getSession().setAttribute(USER_LOGIN_STATE,safeUser);


        return safeUser;
    }

    @Override
    public User getSafeUser(User originUser) {
        if(originUser == null)
            return null;
        User safeUser = new User();
        safeUser.setId(originUser.getId());
        safeUser.setAccount(originUser.getAccount());
        safeUser.setGender(originUser.getGender());
        safeUser.setAge(originUser.getAge());
        safeUser.setAvatarUrl(originUser.getAvatarUrl());
        safeUser.setGoodFocus(originUser.getGoodFocus());
        return safeUser;
    }

    @Override
    public int userLogout(HttpServletRequest request) {
        //移除登录态
        request.getSession().removeAttribute(USER_LOGIN_STATE);
        return 1;
    }

    @Override
    public int updateUser(User user, User LoginUser) {
        long userId = user.getId();
        if(userId <= 0L)
        {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if(LoginUser.getId()!=userId)
        {
            throw new BusinessException(ErrorCode.NO_AUTH);
        }
        User oldUser = userMapper.selectById(userId);
        if(oldUser == null)
        {
            throw new BusinessException(ErrorCode.NULL_ERROR);
        }
        return userMapper.updateById(user);
    }

    @Override
    public User getLoginUser(HttpServletRequest request) {
        if(request == null)
            return null;
        User userObj = (User) request.getSession().getAttribute(USER_LOGIN_STATE);
        if(userObj == null)
        {
            throw new BusinessException(ErrorCode.NOT_LOGIN);
        }
        return userObj;
    }

    @Override
    public List<GoodsVO> seeFavoriteGoods(HttpServletRequest request) {
        User loginUser = this.getLoginUser(request);
        String goodFocus = loginUser.getGoodFocus();
        Set<Integer> goodsSet= gson.fromJson(goodFocus, new TypeToken<Set<Integer>>() {
        }.getType());
        QueryWrapper<Goods> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id",goodsSet);
        List<Goods> goodsList = goodsService.list(queryWrapper);
        return goodsList.stream().map(item -> {
            GoodsVO goodsVO = new GoodsVO();
            BeanUtils.copyProperties(item, goodsVO);
            return goodsVO;
        }).collect(Collectors.toList());
    }

    @Transactional(readOnly = true)
    @Override
    public List<GoodsVO> seeHistoryGoods(HttpServletRequest request) {
        User loginUser = this.getLoginUser(request);
        Integer userId = loginUser.getId();
        QueryWrapper<Goodsviewhistory> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId",userId).orderByDesc("updateTime");
        List<Integer> goodsId = goodsviewhistoryService.list(queryWrapper).stream()
                .map(Goodsviewhistory::getGoodsId).collect(Collectors.toList());
        if(goodsId.isEmpty()){
            return Collections.emptyList();
        }
        QueryWrapper<Goods> goodsQueryWrapper = new QueryWrapper<>();
        goodsQueryWrapper.in("id",goodsId);
        return goodsService.list(goodsQueryWrapper).stream().map(item ->{
            GoodsVO goodsVO = new GoodsVO();
            BeanUtils.copyProperties(item,goodsVO);
            return goodsVO;
        }).collect(Collectors.toList());
    }

    @Override
    public List<String> seeFollowedStore(HttpServletRequest request) {
        User loginUser = this.getLoginUser(request);
        Integer userId = loginUser.getId();
        QueryWrapper<Storefocus> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId",userId);
        return storefocusService.list(queryWrapper)
                .stream().map(Storefocus::getStoreName).collect(Collectors.toList());
    }

    @Override
    public List<GoodsVO> getStoreGoods(String storeName) {
        QueryWrapper<Goods> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("storeName",storeName);
        return goodsService.getGoodsVOS(queryWrapper);
    }

    @Override
    public List<MsgCenter> enterMessageCenter(HttpServletRequest request) {
        User loginUser = this.getLoginUser(request);
        Integer userId = loginUser.getId();
        QueryWrapper<MsgCenter> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId",userId);
        return msgCenterService.list(queryWrapper);
    }

    @Override
    public List<Msg> getMsg(Integer centerId,HttpServletRequest request) {
        User loginUser = this.getLoginUser(request);
        Integer userId = loginUser.getId();
        QueryWrapper<Msg> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId",userId).eq("centerId",centerId);
        return msgService.list(queryWrapper);
    }

    @Override
    public List<Userorder> getOrderInfo(String orderStatus,HttpServletRequest request) {
        User loginUser = this.getLoginUser(request);
        Integer userId = loginUser.getId();
        QueryWrapper<Userorder> queryWrapper = new QueryWrapper<>();
        if("全部".equals(orderStatus)){
            queryWrapper.eq("userId",userId);
        }
        else{
            queryWrapper.eq("userId",userId).eq("orderStatus",orderStatus);
        }
        return userorderService.list(queryWrapper);
    }


}




